/**
*    Copyright (C) 2008  Chase Kernan 
*    chase.kernan@gmail.com
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
**/

package com.chasekernan.hxnova.utils;

/**
    Used mostly by the hull designer, this is just a rectangle made from
    a position and a dimension vector.
**/
class Rectangle {
    
    public var topLeft : Vector;
    public var dimensions(default, setDim) : Vector;
    public var x(getX, setX) : Float;
    public var y(getY, setY) : Float;
    public var width(getWidth, setWidth) : Float;
    public var height(getHeight, setHeight) : Float;
    
    public static function createRectangle(?x = 0.0, ?y = 0.0, ?width = 0.0, 
                                           ?height = 0.0) : Rectangle {
        return new Rectangle(new Vector(x, y), new Vector(width, height));
    }
    
    public function new(?topLeft : Vector, ?dimensions : Vector) {
        this.topLeft = if(topLeft == null) new Vector() else topLeft.clone();
        setDim(if(dimensions == null) new Vector() else dimensions.clone());
    }
    
    private function setDim(v : Vector) {
        if (v.x < 0 || v.y < 0) throw "Cannot set dimensions to less than zero."; 
        dimensions = v.clone(); 
        return dimensions;
    }
    
    private function getX() : Float {
        return topLeft.x;
    }
    
    private function setX(to : Float) : Float {
        topLeft.x = to;
        return to;
    }
    
    private function getY() : Float {
        return topLeft.y;
    }
    
    private function setY(to : Float) : Float {
        topLeft.y = to;
        return to;
    }
    
    private function getWidth() : Float {
        return dimensions.x;
    }
    
    private function setWidth(to : Float) : Float {
        if (to < 0) throw "Width cannot be less than 0.";
        
        dimensions.x = to;
        return to;
    }
    
    private function getHeight() : Float {
        return dimensions.y;
    }
    
    private function setHeight(to : Float) : Float {
        if (to < 0) throw "Height cannot be less than 0.";
        
        dimensions.y = to;
        return to;
    }
	
	public function toString() : String{
		return "[Rectange: x=" + getX() + " y=" + getY() + " width=" + 
				getWidth() + " height=" + getHeight() + "]";
	}
}

#if unit

class RectangleTest extends haxe.unit.TestCase {
    var r : Rectangle;
    
    public function new(){
		super();		
	}
    
    override public function setup() {
        r = new Rectangle(new Vector(2.0, 4.0), new Vector(5.5, 30.2));
    }
    
    public function testNew() {
        assertEquals(2.0, r.topLeft.x);
        assertEquals(4.0, r.topLeft.y);
        assertEquals(5.5, r.dimensions.x);
        assertEquals(30.2, r.dimensions.y);
    }
    
    public function testDimensions() {
        r.dimensions = new Vector(10.0, 5.0);
        assertEquals(10.0, r.dimensions.x);
        assertEquals(5.0, r.dimensions.y);
        
        try {
            r.dimensions = new Vector(-0.2, 0.0);
            assertTrue(false);
        } catch(e : Dynamic) {
            assertTrue(true);
        }
        
        try {
            r.dimensions = new Vector(1.0, -1.0);
            assertTrue(false);
        } catch(e : Dynamic) {
            assertTrue(true);
        }
    }
    
    public function testX() {
        assertEquals(2.0, r.x);
        r.x = -3.2;
        assertEquals(-3.2, r.x);
    }
    
    public function testY() {
        assertEquals(4.0, r.y);
        r.y = -5.0;
        assertEquals(-5.0, r.y);
    }
    
    public function testWidth() {
        assertEquals(5.5, r.width);
        r.width = 3.0;
        assertEquals(3.0, r.width);
        
        try {
            r.width = -5.4;
            assertTrue(false);
        } catch(e : Dynamic) {
            assertTrue(true);
        }
    }
    
    public function testHeight() {
        assertEquals(30.2, r.height);
        r.height = 3.0;
        assertEquals(3.0, r.height);
        
        try {
            r.height = -5.4;
            assertTrue(false);
        } catch(e : Dynamic) {
            assertTrue(true);
        }
    }
    
    public function testCreateRectangle() {
        r = Rectangle.createRectangle(1.0, 2.0, 3.0, 4.0);
        assertEquals(1.0, r.topLeft.x);
        assertEquals(2.0, r.topLeft.y);
        assertEquals(3.0, r.dimensions.x);
        assertEquals(4.0, r.dimensions.y);
    }
}
#end